using System;
using System.Windows.Forms;
using GTA;
using GTA.Math;
using GTA.Native;
using GTA.UI;
using NativeUI;

namespace CustomPeds;

public class Main : Script
{
    public enum MaleStatus
    {
        None,
        OnFoot,
        Vehicle
    }

    public enum FemaleStatus
    {
        None,
        Accompany
    }

    public enum Member
    {
        P1,
        P2,
        P3,
        P4,
        Clone
    }

    public static MenuPool pool = new MenuPool();
    public static MaleStatus m_Status;
    public static FemaleStatus f_Status;
    public static Origin P1 = new Origin();
    public static Origin P2 = new Origin();
    public static Origin P3 = new Origin();
    public static Origin Clone = new Origin();
    public static bool isMainMenuVisible;
    private static bool isStartKeyDown;

    public Main()
    {
        KeyDown += OnKeyDown;
        KeyUp += OnKeyUp;
        Tick += OnTick;
        Interval = 0;
        LogHelper.InitializeLog();
        LogHelper.WriteInfo("CustomPeds Pro 已初始化");
        // 预初始化主要菜单脚本，确保按键后可立即打开并已加入 MenuPool
        try
        {
            new Menus.MainMenu();
            new Menus.PlayerMenu();
            new Menus.GirlfriendMenu();
            new Menus.OnFootMainMenu();
            new Menus.VehicleMainMenu();
        }
        catch { }
    }

    public static void OnMainMenuHidden()
    {
        isMainMenuVisible = false;
        isStartKeyDown = false;
    }

    private void OnKeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == ScriptSettings.startKey)
        {
            // 防抖：仅在首次按下触发
            if (isStartKeyDown)
            {
                return;
            }
            isStartKeyDown = true;
            try { LogHelper.WriteInfo("KeyDown: startKey pressed, toggling main menu"); } catch { }

            if (!isMainMenuVisible)
            {
                InitMale();
                try { LogHelper.WriteInfo("Opening MainMenu"); } catch { }
                // 打开主菜单前刷新互动项的可用状态（包含女友距离>40f禁用）
                try
                {
                    var items = Menus.MainMenu.menu.MenuItems;
                    if (items != null && items.Count >= 3)
                    {
                        var interact = items[2];
                        bool inVeh = P1.Character != null && P1.Character.IsInVehicle();
                        bool isDriver = inVeh && IsPedDriverOfCurrentVehicle(P1.Character);
                        bool gfNear = IsGirlfriendInNear(40f);
                        interact.Enabled = (((!inVeh) || isDriver) && gfNear);
                    }
                }
                catch { }
                Menus.MainMenu.menu.Visible = true;
                Menus.MainMenu.menu.RefreshIndex();
                isMainMenuVisible = true;
            }
            else
            {
                Menus.MainMenu.menu.Visible = false;
                isMainMenuVisible = false;
            }
        }
    }

    private void OnKeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == ScriptSettings.startKey)
        {
            isStartKeyDown = false;
        }
    }

    private void OnTick(object sender, EventArgs e)
    {
        if (pool != null && pool.IsAnyMenuOpen())
        {
            pool.ProcessMenus();
        }
    }

    public static bool IsPedDriverOfCurrentVehicle(Ped ped)
    {
        try
        {
            if (ped == null || !ped.IsInVehicle())
            {
                return false;
            }
            var v = ped.CurrentVehicle;
            return v != null && v.Exists() && v.Driver != null && v.Driver.Exists() && v.Driver.Handle == ped.Handle;
        }
        catch
        {
            return false;
        }
    }

    public static bool IsPedInSeat(Vehicle vehicle, Ped ped, VehicleSeat seat)
    {
        try
        {
            if (vehicle == null || ped == null || !vehicle.Exists() || !ped.Exists())
            {
                return false;
            }
            if (seat == VehicleSeat.Driver)
            {
                return vehicle.Driver != null && vehicle.Driver.Exists() && vehicle.Driver.Handle == ped.Handle;
            }
            var occ = vehicle.GetPedOnSeat(seat);
            return occ != null && occ.Exists() && occ.Handle == ped.Handle;
        }
        catch
        {
            return false;
        }
    }

    public static bool IsSeatFree(Vehicle vehicle, VehicleSeat seat)
    {
        try
        {
            if (vehicle == null || !vehicle.Exists())
            {
                return false;
            }
            if (seat == VehicleSeat.Driver)
            {
                return vehicle.Driver == null || !vehicle.Driver.Exists() || vehicle.Driver.Handle == 0;
            }
            var occ = vehicle.GetPedOnSeat(seat);
            return occ == null || !occ.Exists() || occ.Handle == 0;
        }
        catch
        {
            return false;
        }
    }

    public static bool EnsureDriverAndPassenger(Vehicle vehicle, Ped driverPed, Ped passengerPed, int timeoutMs = 8000)
    {
        try
        {
            if (vehicle == null || !vehicle.Exists())
            {
                return false;
            }
            if (!IsPedDriverOfCurrentVehicle(driverPed))
            {
                if (vehicle.Driver != null && vehicle.Driver.Exists() && driverPed != null && vehicle.Driver.Handle != driverPed.Handle)
                {
                    vehicle.Driver.Task.LeaveVehicle();
                    Wait(500);
                }
                driverPed?.Task.EnterVehicle(vehicle, VehicleSeat.Driver, 1500, 2f, EnterVehicleFlags.WarpIn);
            }
            var start = DateTime.Now;
            while (!IsPedDriverOfCurrentVehicle(driverPed))
            {
                if ((DateTime.Now - start).TotalMilliseconds > timeoutMs)
                {
                    break;
                }
                Wait(100);
            }
            var passengerSeat = GetFirstAvailablePassengerSeat(vehicle);
            if (passengerPed != null && passengerSeat != VehicleSeat.Any && !IsPedInSeat(vehicle, passengerPed, passengerSeat))
            {
                passengerPed.Task.EnterVehicle(vehicle, passengerSeat, 1500, 2f, EnterVehicleFlags.WarpIn);
                var pStart = DateTime.Now;
                while (!IsPedInSeat(vehicle, passengerPed, passengerSeat))
                {
                    if ((DateTime.Now - pStart).TotalMilliseconds > timeoutMs)
                    {
                        break;
                    }
                    Wait(100);
                }
            }
            return IsPedDriverOfCurrentVehicle(driverPed);
        }
        catch
        {
            return false;
        }
    }

    private static VehicleSeat GetFirstAvailablePassengerSeat(Vehicle vehicle)
    {
        try
        {
            if (vehicle == null || !vehicle.Exists())
            {
                return VehicleSeat.Any;
            }
            // SHVDN3 无 PassengerSeats，按最多 16 个乘客位扫描（原生索引 0..15，-1 为 Driver）
            for (int i = 0; i < 16; i++)
            {
                var seat = (VehicleSeat)i;
                if (IsSeatFree(vehicle, seat))
                {
                    return seat;
                }
            }
            return VehicleSeat.Any;
        }
        catch
        {
            return VehicleSeat.Any;
        }
    }

    public static void InitMale()
    {
        if (P1.Character == null)
        {
            P1.Character = Game.Player.Character;
            P1.Character.CanWearHelmet = P1.CanWearHelmet;
            P1.Character.VehicleDrivingFlags = P1.drivingFlags;
            P1.BuildPedData(P1.Character, Member.P1, isAddonPed: false);
        }
    }

    public static void InitFemale()
    {
        if (P2.Character != null)
        {
            return;
        }
        try
        {
            P2.Character = CreatePed(PedHash.AmandaTownley);
            if (P2.Character != null)
            {
                P2.Character.Task.LookAt(P1.Character);
                P2.Character.BlockPermanentEvents = true;
                P2.Character.IsPersistent = true;
                P2.Character.CanWearHelmet = P2.CanWearHelmet;
                // 默认驾驶模式为“正常”，默认副驾
                P2.drivingFlags = VehicleDrivingFlags.DrivingModeStopForVehicles;
                P2.SeatIndex = 0;
                if (P2.Follow)
                {
                    P1.Character.PedGroup.Add(P2.Character, leader: false);
                }
                P2.Character.IsInvincible = P2.Invincible;
                P2.Character.VehicleDrivingFlags = P2.drivingFlags;
                P2.BuildPedData(P2.Character, Member.P2, isAddonPed: false);
                // 将 P1 的武器配置同步给 P2
                if (P1.skin != null)
                {
                    P2.skin.SetWeapons(P1.skin.GetWeaponsData());
                }
                f_Status = FemaleStatus.Accompany;
            }
        }
        catch (Exception ex)
        {
            Notification.PostTicker($"创建女友失败: {ex.Message}", true, false);
        }
    }

    public static bool IsGirlfriendInNear(float radius)
    {
        if (P2.Character == null)
        {
            return false;
        }
        try
        {
            Ped[] nearbyPeds = World.GetNearbyPeds(P1.Character, radius);
            for (int i = 0; i < nearbyPeds.Length; i++)
            {
                if (nearbyPeds[i] != null && nearbyPeds[i].Handle == P2.Character.Handle)
                {
                    return true;
                }
            }
        }
        catch
        {
        }
        return false;
    }

    public static void ReBuildP2(Ped ped, string modelName, bool isAddonPed = false)
    {
        try
        {
            if (ped != null && Game.Player.Character.PedGroup.Contains(ped))
            {
                ped.LeaveGroup();
            }
            if (ped != null)
            {
                ped.MarkAsNoLongerNeeded();
                ped.Delete();
            }
            ped = CreatePed(modelName, isAddonPed);
            if (ped == null)
            {
                ped = CreatePed(PedHash.AmandaTownley);
                isAddonPed = false;
            }
            P2.Character = ped;
            P2.Character.BlockPermanentEvents = true;
            P2.Character.IsPersistent = true;
            P2.Character.SetDefaultClothes();
            // 默认驾驶模式为“正常”，默认副驾
            P2.drivingFlags = VehicleDrivingFlags.DrivingModeStopForVehicles;
            P2.SeatIndex = 0;
            P2.Character.VehicleDrivingFlags = P2.drivingFlags;
            P2.BuildPedData(P2.Character, Member.P2, isAddonPed);
            f_Status = FemaleStatus.Accompany;
        }
        catch (Exception ex)
        {
            Notification.PostTicker($"重建女友失败: {ex.Message}", true, false);
        }
    }

    public static void ReBuildClone(Ped ped, string modelName, bool isAddonPed = false)
    {
        try
        {
            if (ped != null)
            {
                ped.MarkAsNoLongerNeeded();
                ped.Delete();
            }
            ped = CreatePed(modelName, isAddonPed);
            if (ped == null)
            {
                ped = CreatePed(PedHash.Franklin);
            }
            Clone.Character = ped;
            Clone.Character.BlockPermanentEvents = true;
            Clone.Character.IsPersistent = true;
            Clone.Character.SetDefaultClothes();
            Clone.skin = new Skin(ped, isAddonPed);
        }
        catch (Exception ex)
        {
            Notification.PostTicker($"重建克隆失败: {ex.Message}", true, false);
        }
    }

    public static bool ChangePlayerModel(string pedName, bool isAddonPed = false)
    {
        bool flag = true;
        Model model = null;
        try
        {
            model = (!isAddonPed) ? new Model((PedHash)Enum.Parse(typeof(PedHash), pedName)) : new Model(pedName);
            bool flag2 = model.Request(5000);
            if (model.IsInCdImage && model.IsValid && flag2)
            {
                Ped ped = World.CreatePed(model, Game.Player.Character.GetOffsetPosition(new Vector3(0f, -20f, -1f)), Game.Player.Character.Heading - 180f);
                ped.IsVisible = false;
                Wait(500);
                if (ped.Bones[Bone.RBLeftArmRoll].Index == -1 && !isAddonPed)
                {
                    flag = false;
                }
                ped.MarkAsNoLongerNeeded();
                ped.Delete();
                if (flag)
                {
                    Function.Call((Hash)0x00A1CADD00108836ul, Game.Player, model.Hash);
                }
            }
            else
            {
                flag = false;
            }
        }
        catch (Exception ex)
        {
            flag = false;
            Notification.PostTicker($"更换模型失败: {ex.Message}", true, false);
        }
        finally
        {
            if (model != null)
            {
                model.MarkAsNoLongerNeeded();
            }
        }
        return flag;
    }

    public static Ped CreatePed(string pedName, bool isAddonPed = false)
    {
        Ped ped = null;
        Model model = null;
        try
        {
            model = (!isAddonPed) ? new Model((PedHash)Enum.Parse(typeof(PedHash), pedName)) : new Model(pedName);
            bool flag = model.Request(5000);
            if (model.IsInCdImage && model.IsValid && flag)
            {
                ped = World.CreatePed(model, Game.Player.Character.GetOffsetPosition(new Vector3(0f, 2f, -1f)), Game.Player.Character.Heading - 180f);
                ped.IsVisible = false;
                Wait(500);
                if (ped.Bones[Bone.RBLeftArmRoll].Index == -1 && !isAddonPed)
                {
                    ped.MarkAsNoLongerNeeded();
                    ped.Delete();
                    ped = null;
                }
            }
            if (ped != null)
            {
                ped.IsVisible = true;
            }
        }
        catch (Exception ex)
        {
            Notification.PostTicker($"创建Ped失败: {ex.Message}", true, false);
        }
        finally
        {
            if (model != null)
            {
                model.MarkAsNoLongerNeeded();
            }
        }
        return ped;
    }

    public static Ped CreatePed(PedHash pedHash)
    {
        Ped ped = null;
        Model model = null;
        try
        {
            model = new Model(pedHash);
            bool flag = model.Request(5000);
            if (model.IsInCdImage && model.IsValid && flag)
            {
                ped = World.CreatePed(model, Game.Player.Character.GetOffsetPosition(new Vector3(0f, 2f, -0.5f)), Game.Player.Character.Heading - 180f);
                ped.IsVisible = false;
                Wait(500);
                if (ped.Bones[Bone.RBLeftArmRoll].Index == -1)
                {
                    ped.MarkAsNoLongerNeeded();
                    ped.Delete();
                    ped = null;
                }
            }
            if (ped != null)
            {
                ped.IsVisible = true;
            }
            else
            {
                ped = CreatePed(PedHash.AmandaTownley);
            }
        }
        catch (Exception ex)
        {
            Notification.PostTicker($"创建Ped失败: {ex.Message}", true, false);
        }
        finally
        {
            if (model != null)
            {
                model.MarkAsNoLongerNeeded();
            }
        }
        return ped;
    }
}


